/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PANDA_COMPILER_ECMASCRIPT_ENVIRONMENT_H
#define PANDA_COMPILER_ECMASCRIPT_ENVIRONMENT_H

#include <cstddef>
#include "runtime/include/object_header.h"
#include "runtime/mem/object_helpers.h"
#include "libpandabase/mem/mem.h"
#include "runtime/include/coretypes/tagged_value.h"

namespace ark {

class ObjectHeader;

namespace ecmascript {

template <typename T>
class JSHandle;

class EcmascriptEnvironment {
public:
    EcmascriptEnvironment(ObjectHeader *cp, ObjectHeader *le, ObjectHeader *tf)
        : constantPool_(cp), lexicalEnv_(le), thisFunc_(tf)
    {
    }

    static EcmascriptEnvironment *Cast(void *data)
    {
        return static_cast<EcmascriptEnvironment *>(data);
    }

    static constexpr size_t GetConstantPoolOffset()
    {
        return MEMBER_OFFSET(EcmascriptEnvironment, constantPool_);
    }

    static constexpr size_t GetLexicalEnvOffset()
    {
        return MEMBER_OFFSET(EcmascriptEnvironment, lexicalEnv_);
    }

    static constexpr size_t GetThisFuncOffset()
    {
        return MEMBER_OFFSET(EcmascriptEnvironment, thisFunc_);
    }

    ObjectHeader *GetConstantPool() const
    {
        return constantPool_.GetHeapObject();
    }

    ObjectHeader *GetLexicalEnv() const
    {
        return lexicalEnv_.GetHeapObject();
    }

    void SetLexicalEnv(ObjectHeader *le)
    {
        lexicalEnv_ = ark::coretypes::TaggedValue(le);
    }

    void SetConstantPool(ObjectHeader *cp)
    {
        constantPool_ = ark::coretypes::TaggedValue(cp);
    }

    ObjectHeader *GetThisFunc() const
    {
        return thisFunc_.GetHeapObject();
    }

    void SetThisFunc(ObjectHeader *thisFunc)
    {
        thisFunc_ = ark::coretypes::TaggedValue(thisFunc);
    }

    static constexpr size_t GetSize()
    {
        return AlignUp(sizeof(EcmascriptEnvironment), GetAlignmentInBytes(DEFAULT_FRAME_ALIGNMENT));
    }

private:
    ark::coretypes::TaggedValue constantPool_;
    ark::coretypes::TaggedValue lexicalEnv_;
    ark::coretypes::TaggedValue thisFunc_;
};

}  // namespace ecmascript

}  // namespace ark

#endif  // PANDA_COMPILER_ECMASCRIPT_ENVIRONMENT_H
